<template>
  <div class="bpmn-designer">
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span>BPMN 流程设计器</span>
          <div class="toolbox">
            <el-button-group>
              <el-button type="primary" @click="downloadXML">
                <el-icon><Download /></el-icon>下载XML
              </el-button>
              <el-button type="primary" @click="downloadSVG">
                <el-icon><PictureFilled /></el-icon>下载SVG
              </el-button>
              <el-button type="success" @click="deploy">
                <el-icon><Upload /></el-icon>部署流程
              </el-button>
              <el-button type="warning" @click="openFile">
                <el-icon><FolderOpened /></el-icon>打开文件
              </el-button>
              <el-button type="danger" @click="clearCanvas">
                <el-icon><Delete /></el-icon>清空画布
              </el-button>
            </el-button-group>
          </div>
        </div>
      </template>

      <div class="canvas-container">
        <div id="bpmn-canvas" ref="bpmnCanvas"></div>
        <div id="properties-panel" ref="propertiesPanel"></div>
      </div>
    </el-card>

    <el-dialog v-model="deployDialogVisible" title="部署流程" width="500px">
      <el-form :model="deployForm" label-width="100px">
        <el-form-item label="流程名称">
          <el-input v-model="deployForm.name" placeholder="请输入流程名称"></el-input>
        </el-form-item>
        <el-form-item label="流程Key">
          <el-input v-model="deployForm.key" placeholder="请输入流程Key"></el-input>
        </el-form-item>
        <el-form-item label="所属分类">
          <el-select v-model="deployForm.category" placeholder="请选择分类">
            <el-option label="人事" value="hr"></el-option>
            <el-option label="财务" value="finance"></el-option>
            <el-option label="采购" value="purchase"></el-option>
            <el-option label="销售" value="sales"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="deployDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmDeploy">确认部署</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import BpmnModeler from 'bpmn-js/lib/Modeler'
import { is } from 'bpmn-js/lib/util/ModelUtil'
import { getBpmnColor } from 'diagram-js/lib/draw/BpmnRenderUtil'
import propertiesPanelModule from 'bpmn-js-properties-panel'
import { saveAs } from 'file-saver'

// BPMN 相关引用
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import 'bpmn-js-properties-panel/dist/assets/properties-panel.css'

// 引用默认空白流程图 XML
const emptyXML = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                  xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" 
                  xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" 
                  xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" 
                  xmlns:di="http://www.omg.org/spec/DD/20100524/DI" 
                  id="Definitions_1" 
                  targetNamespace="http://bpmn.io/schema/bpmn">
  <bpmn:process id="Process_1" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1"/>
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="173" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>`

// DOM 引用
const bpmnCanvas = ref(null)
const propertiesPanel = ref(null)

// BPMN 建模器实例
let bpmnModeler = null

// 部署对话框
const deployDialogVisible = ref(false)
const deployForm = ref({
  name: '',
  key: '',
  category: ''
})

// 初始化 BPMN 建模器
const initBpmnModeler = () => {
  // 创建 BPMN 建模器实例
  bpmnModeler = new BpmnModeler({
    container: bpmnCanvas.value,
    propertiesPanel: {
      parent: propertiesPanel.value
    },
    additionalModules: [
      propertiesPanelModule
    ]
  })

  // 导入默认空白流程图
  bpmnModeler.importXML(emptyXML).then(({ warnings }) => {
    if (warnings.length) {
      console.warn('有一些导入警告：', warnings)
    }
    // 调整画布视图，使其充满可视区域
    bpmnModeler.get('canvas').zoom('fit-viewport')
  }).catch(err => {
    console.error('导入失败：', err)
  })

  // 添加修改监听事件
  bpmnModeler.on('element.changed', (event) => {
    const element = event.element
    if (is(element, 'bpmn:StartEvent')) {
      console.log('开始事件被修改')
    }
  })
}

// 下载 XML 文件
const downloadXML = async () => {
  try {
    const { xml } = await bpmnModeler.saveXML({ format: true })
    const blob = new Blob([xml], { type: 'application/xml;charset=UTF-8' })
    saveAs(blob, 'process.bpmn')
    ElMessage.success('XML 下载成功')
  } catch (err) {
    ElMessage.error('XML 下载失败')
    console.error(err)
  }
}

// 下载 SVG 文件
const downloadSVG = async () => {
  try {
    const { svg } = await bpmnModeler.saveSVG()
    const blob = new Blob([svg], { type: 'image/svg+xml;charset=UTF-8' })
    saveAs(blob, 'process.svg')
    ElMessage.success('SVG 下载成功')
  } catch (err) {
    ElMessage.error('SVG 下载失败')
    console.error(err)
  }
}

// 打开文件
const openFile = () => {
  const fileInput = document.createElement('input')
  fileInput.type = 'file'
  fileInput.accept = '.bpmn,.xml'
  fileInput.onchange = (e) => {
    const file = e.target.files[0]
    if (!file) return
    
    const reader = new FileReader()
    reader.onload = (e) => {
      const xmlContent = e.target.result
      bpmnModeler.importXML(xmlContent).then(({ warnings }) => {
        if (warnings.length) {
          console.warn('有一些导入警告：', warnings)
        }
        ElMessage.success('文件导入成功')
        bpmnModeler.get('canvas').zoom('fit-viewport')
      }).catch(err => {
        ElMessage.error('文件导入失败')
        console.error('导入失败：', err)
      })
    }
    reader.readAsText(file)
  }
  fileInput.click()
}

// 清空画布
const clearCanvas = () => {
  ElMessageBox.confirm('确定要清空画布吗？此操作不可恢复！', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    bpmnModeler.importXML(emptyXML).then(() => {
      ElMessage.success('画布已清空')
      bpmnModeler.get('canvas').zoom('fit-viewport')
    })
  }).catch(() => {})
}

// 部署流程
const deploy = () => {
  deployForm.value = {
    name: '',
    key: '',
    category: ''
  }
  deployDialogVisible.value = true
}

// 确认部署
const confirmDeploy = async () => {
  if (!deployForm.value.name || !deployForm.value.key) {
    ElMessage.warning('请输入流程名称和流程Key')
    return
  }

  try {
    const { xml } = await bpmnModeler.saveXML({ format: true })
    
    // 这里应该调用 API 来部署流程
    // 这里只是模拟部署
    ElMessage.success('流程部署成功')
    deployDialogVisible.value = false
  } catch (err) {
    ElMessage.error('流程部署失败')
    console.error(err)
  }
}

onMounted(() => {
  initBpmnModeler()
})

onBeforeUnmount(() => {
  if (bpmnModeler) {
    bpmnModeler.destroy()
  }
})
</script>

<style scoped>
.bpmn-designer {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.canvas-container {
  display: flex;
  width: 100%;
  height: calc(100vh - 200px);
  min-height: 500px;
  border: 1px solid #dcdfe6;
  margin-top: 20px;
}

#bpmn-canvas {
  flex: 1;
  height: 100%;
  position: relative;
  border-right: 1px solid #dcdfe6;
}

#properties-panel {
  width: 300px;
  height: 100%;
  overflow: auto;
  padding: 10px;
  background-color: #f5f7fa;
}

/* 覆盖 BPMN.js 默认样式 */
:deep(.djs-palette) {
  top: 10px;
  left: 10px;
}

:deep(.djs-context-pad) {
  z-index: 1000;
}

:deep(.bpmn-icon-task) {
  color: #409EFF;
}

:deep(.bpmn-icon-start-event-none) {
  color: #67C23A;
}

:deep(.bpmn-icon-end-event-none) {
  color: #F56C6C;
}

:deep(.bpmn-icon-gateway-none) {
  color: #E6A23C;
}
</style> 